﻿using UnityEngine;
using System.Collections.Generic;
using ProtoBuf.Message;

namespace Room
{
    //public delegate void TransferCallback();
    public class RoomNetBase
    {
        protected Queue<Position> queueRoleMove = new Queue<Position>();
        protected Queue<MovePlayer> queueRoleAppear = new Queue<MovePlayer>();
        protected Queue<long> queueRoleDisappear = new Queue<long>();
        protected Queue<MovePlayer> queueRoleInfo = new Queue<MovePlayer>();

        protected Dictionary<long, Vector3> willLoadPlayer = new Dictionary<long, Vector3>();

        protected Queue<PlayerSide> playerSideQueue = new Queue<PlayerSide>();

        protected Dictionary<long, string> petInfos = new Dictionary<long, string>();

        //protected TransferCallback callback;

        protected float lastCommitTime = 0f;
        protected Vector3 lastPosition;

        protected bool running = false;

        protected RoomBase roomBase;

        protected float enterTime;
        protected int initState;

        public virtual void Init(RoomBase r)
        {
            roomBase = r;
        }

        public virtual void Tick()
        {
            while (queueRoleAppear.Count > 0)
            {
                SolveRoleAppear(queueRoleAppear.Dequeue());
            }
            while (queueRoleMove.Count > 0)
            {
                SolveRoleMove(queueRoleMove.Dequeue());
            }
            while (queueRoleDisappear.Count > 0)
            {
                SolveRoleDisappear(queueRoleDisappear.Dequeue());
            }
            while (queueRoleInfo.Count > 0)
            {
                SolveRoleInfo(queueRoleInfo.Dequeue());
            }

            if (willLoadPlayer.Count > 0)
            {
                CSMovePlayerInfo mpi = new CSMovePlayerInfo();
                var enm = willLoadPlayer.GetEnumerator();
                while (enm.MoveNext())
                {
                    mpi.playerIds.Add(enm.Current.Key);
                }
                NetAPI.SendSocket(OpDefine.CSMovePlayerInfo, mpi);
                willLoadPlayer.Clear();
            }

            if (initState == 2)
            {
                SyncSelfToServer();
            }

            if (initState == 1 && Time.unscaledTime - enterTime > 10)
            {
                SCCurrentPosition sccp = new ProtoBuf.Message.SCCurrentPosition();
                sccp.limit = 50;
                sccp.self = new MovePlayer();
                sccp.self.position = new Position();
                sccp.self.position.current = new PointNew();
                sccp.self.position.current.x = 2f;
                sccp.self.position.current.z = 2f;
                sccp.self.position.current.y = 0f;
                //sccp.self.position.scene = 
                sccp.self.position.playerId = StaticData.playerData.playerId;
                sccp.self.info = new MovePlayerInfo();
                sccp.self.info.playerId = StaticData.playerData.playerId;
                sccp.self.info.playerName = StaticData.playerData.name;
                //sccp.self.info.kills = 6;
                var heroCamp = StaticData.playerData.InstPlayerData.GetBattleCamp(1);
                sccp.self.info.warId = heroCamp.hero.heroId;
                sccp.self.info.equipId = heroCamp.equipments[0] == null ? null : heroCamp.equipments[0].equipId;
                sccp.self.info.playerSide = new PlayerSide();
                Debug.LogError("Can't get init position!!");
                SCCurrentPosition(sccp);
            }

        }

        public virtual void Enter()
        {
            NetAPI.CurrSceneId = (int)roomBase.GetServerType();
            RegistSocketHandler();
            DataMessageTool.AddHandler(DataMessage.NET_CONNECT_COMPLETE, SendCSCurrentPosition);
            enterTime = Time.unscaledTime;
            initState = 1;
            SendCSCurrentPosition(null);
        }

        public virtual void Leave()
        {
            UnRegistSocketHandler();
            queueRoleAppear.Clear();
            queueRoleDisappear.Clear();
            queueRoleMove.Clear();
            queueRoleInfo.Clear();
            willLoadPlayer.Clear();

            DataMessageTool.RemoveHandler(DataMessage.NET_CONNECT_COMPLETE, SendCSCurrentPosition);


        }

        public virtual void Resume()
        {
        }

        public virtual void Pause()
        {
        }

        public virtual void RegistSocketHandler()
        {

            #region 移动和位置
            NetAPI.RegistSocketHandler(OpDefine.SCCurrentPosition, SCCurrentPosition); //第一次拉取
            NetAPI.RegistSocketHandler(OpDefine.SCMovePush, SCMovePush);
            NetAPI.RegistSocketHandler(OpDefine.SCPlayerAppear, SCPlayerAppear);
            NetAPI.RegistSocketHandler(OpDefine.SCPlayerDisappear, SCPlayerDisappear);
            NetAPI.RegistSocketHandler(OpDefine.SCMovePlayerInfo, SCMovePlayerInfo);
            #endregion
            

           // NetAPI.RegistSocketHandler(OpDefine.SCSceneChatCache, SCSceneChatCache);
        }

        public virtual void UnRegistSocketHandler()
        {
            #region 移动和位置
            NetAPI.UnregisterSocketHandler(OpDefine.SCCurrentPosition, SCCurrentPosition); //第一次拉取
            NetAPI.UnregisterSocketHandler(OpDefine.SCMovePush, SCMovePush);
            NetAPI.UnregisterSocketHandler(OpDefine.SCPlayerAppear, SCPlayerAppear);
            NetAPI.UnregisterSocketHandler(OpDefine.SCPlayerDisappear, SCPlayerDisappear);
            NetAPI.UnregisterSocketHandler(OpDefine.SCMovePlayerInfo, SCMovePlayerInfo);
            #endregion
            

            //  NetAPI.UnregisterSocketHandler(OpDefine.SCSceneChatCache, SCSceneChatCache);
        }

        
        //protected virtual void SCSceneChatCache(object obj)
        //{
        //    SCSceneChatCache msg = obj as SCSceneChatCache;
        //    Chat.ChatManager.Instance.ReceiveChat(msg.chatList);
        //}


        #region Common Method
        protected virtual void SolveRoleAppear(MovePlayer player)
        {
            MovePlayerInfo info = player.info;
            Position pos = player.position;

            if (info == null || pos == null)
                return;
            if (info.playerId.ToString().Equals(roomBase.charactorManager.GetSelfId()))
            {
                Debug.LogError("Receive self appear message ,id " + info.playerId);
                return;
            }
            if (willLoadPlayer.ContainsKey(info.playerId))
            {
                willLoadPlayer.Remove(info.playerId);
            }

            if (RoomManager.curSceneType == SceneType.FIELD)
            {
                var currStr = ServerScene.Field + StaticData.fieldId;
                var sceneStr = pos.scene;
                if (!sceneStr.StartsWith(currStr))
                {
                    return;
                }
            }
            else if (RoomManager.curSceneType == SceneType.TOWN)
            {
                var currStr = ServerScene.Town;
                var sceneStr = pos.scene;
                if (!sceneStr.StartsWith(currStr))
                {
                    return;
                }
            }
	
			roomBase.charactorManager.CreateOtherPlayer(info.playerId.ToString(), info.warId, info.playerName, info.equipId,info.title,info.unionName,info.serverId);
            var charactor = roomBase.charactorManager.GetCharactor(info.playerId.ToString());
            charactor.transform.position = new Vector3(pos.current.x, pos.current.y, pos.current.z);
            charactor.transform.localEulerAngles = new Vector3(0.0f, Random.Range(0, 360), 0.0f);//人物角度


            var ai = charactor.ai as RCAIActor;
            charactor.SetKillNum(player.info.playerSide.kills);
            if(ai!=null)
                ai.SwitchState(PlayerAIState.Normal);

            var ui = charactor.ui as RCUIPlayer;
			ui.SetTitle(info.title);
            ui.SetUinonServer(info.unionName, info.serverId);
            //Debug.Log("role appear playerid = " + info.playerId);

            if(!string.IsNullOrEmpty(info.petId))
            {
                roomBase.charactorManager.CreatePet(info.petId, info.playerId+"");
                petInfos[info.playerId] = info.petId;
            }
        }

        protected virtual void SolveRoleDisappear(long id)
        {
            if(petInfos.ContainsKey(id))
            {
                roomBase.charactorManager.DestroyCharactor(petInfos[id]);
                petInfos.Remove(id);
            }
            roomBase.charactorManager.DestroyCharactor(id.ToString());
            
            if (willLoadPlayer.ContainsKey(id))
            {
                willLoadPlayer.Remove(id);
            }
        }

        protected virtual void SolveRoleMove(Position pos)
        {
            var ch = roomBase.charactorManager.GetCharactor(pos.playerId.ToString());
            if (ch != null)
            {
                if (ch.type == CharactorType.SelfPlayer)
                {
                    Debug.LogWarning("receive self move msg");
                    ch.StopTo(new Vector3(pos.current.x, pos.current.y, pos.current.z));
                }
                else
                {
                    ch.StopTo(new Vector3(pos.current.x, pos.current.y, pos.current.z));
                }

            }
            else
            {
                //Debug.Log("will player move id " + pos.playerId);
                willLoadPlayer[pos.playerId] = new Vector3(pos.current.x, pos.current.y, pos.current.z);
            }
        }

        protected virtual void SolveRoleInfo(MovePlayer info)
        {

            if (RoomManager.curSceneType == SceneType.FIELD)
            {
                var currStr = ServerScene.Field + StaticData.fieldId;
                var sceneStr = info.position.scene;
                if (!sceneStr.StartsWith(currStr))
                {
                    return;
                }
            }
            else if (RoomManager.curSceneType == SceneType.TOWN)
            {
                var currStr = ServerScene.Town;
                var sceneStr = info.position.scene;
                if (!sceneStr.StartsWith(currStr))
                {
                    return;
                }
            }

            var charactor = roomBase.charactorManager.GetCharactor(info.info.playerId.ToString());
            if (charactor != null)
            {
                RCLODPlayer lodPlayer = charactor.lod as RCLODPlayer;
                if (lodPlayer != null)
                {
                    lodPlayer.Refresh(info.info.warId, info.info.equipId);
                }
                charactor.SetKillNum(info.info.playerSide.kills);

                RCUIPlayer uiPlayer = charactor.ui as RCUIPlayer;
                if (uiPlayer != null)
                {
					uiPlayer.SetTitle(info.info.title);
                    uiPlayer.SetUinonServer(info.info.unionName, info.info.serverId);
                    var name = info.info.playerName;
                }
            }
            else
            {
				charactor = roomBase.charactorManager.CreateOtherPlayer(info.info.playerId.ToString(), info.info.warId, info.info.playerName, info.info.equipId,info.info.title,
					info.info.unionName,info.info.serverId);
                roomBase.charactorManager.SetPosition(info.info.playerId.ToString(), new Vector3(info.position.current.x,
                    info.position.current.y, info.position.current.z));
                charactor.SetKillNum(info.info.playerSide.kills);
                charactor.transform.localEulerAngles = new Vector3(0.0f, Random.Range(0, 360), 0.0f);//人物角度
                if (willLoadPlayer.ContainsKey(info.info.playerId))
                {
                    willLoadPlayer.Remove(info.info.playerId);
                }

                var ui = (charactor.ui as RCUIPlayer);
                if (ui != null)
                {
					
					ui.SetTitle(info.info.title);
                    ui.SetUinonServer(info.info.unionName, info.info.serverId);
                }

                if (info!=null && info.info!=null && !string.IsNullOrEmpty(info.info.petId))
                {
                    roomBase.charactorManager.CreatePet(info.info.petId, info.info.playerId + "");
                    petInfos[info.info.playerId] = info.info.petId;
                }

            }
            
        }

        protected virtual void SolveChatInfo(ChatInfo info)
        {
            var charactor = roomBase.charactorManager.GetCharactor(info.playerId.ToString());
            if (charactor != null)
            {

                charactor.ShowBubble(info.content);
            }
        }

        protected virtual void SyncSelfToServer()
        {
            RoomCharactor self = roomBase.charactorManager.GetSelfCharactor();
            if (self == null)
            {
                return;
            }

            if (Time.time - lastCommitTime < 0.5f)
                return;
            lastCommitTime = Time.time;

            Vector3 pos = self.transform.position;

            if (lastPosition == pos)
            {
                return;
            }
            lastPosition = pos;

            CSMove msg = new CSMove();
            PointNew p = new PointNew();
            p.x = pos.x;
            p.y = pos.y;
            p.z = pos.z;
            

            msg.pointNew = p;
            NetAPI.SendSocket(OpDefine.CSMove, msg);

        }
        #endregion

        #region Send
        public virtual void SendCSCurrentPosition(object sender)
        {
            CSCurrentPosition msg = new CSCurrentPosition();
            //#if UNITY_EDITOR
            //BoxManager.CreatePopupTextBox("CSCurrentPosition");
            Debug.Log("<color=yellow> CSCurrentPosition </color>");
            //#endif
            NetAPI.SendSocket(OpDefine.CSCurrentPosition, msg);
        }
        #endregion


        #region Common Callback
        protected virtual void SCCurrentPosition(object obj)
        {
            SCCurrentPosition msg = obj as SCCurrentPosition;
            StaticData.maxPlayerInView = msg.limit;
            MovePlayer self = msg.self;
            initState = 2;
            //self.info.title
            
            roomBase.charactorManager.CreateSelfPlayer(self.info.playerId.ToString(), self.info.warId, self.info.equipId, self.info.playerName,self.info.title,self.info.unionName,self.info.serverId);
            PointNew p = self.position.current;
            var ch = roomBase.charactorManager.GetSelfCharactor();
            ch.transform.position = new Vector3(p.x, p.y, p.z);
            ch.transform.localEulerAngles = new Vector3(0, Random.Range(0, 360), 0);
            lastPosition = ch.transform.position;
            roomBase.OnMainCharactorLoaded(ch.transform);
            var ai = roomBase.charactorManager.GetSelfCharactor().ai as RCAIActor;
            ai.SwitchState(PlayerAIState.Normal);
            if (self.info != null)
            {
                StaticData.playerData.teamId = self.info.teamId;
                Debug.Log("[team info] teamId:" + self.info.teamId);
            }

            ///处理疲劳值
            if (msg != null && msg.self != null && msg.self.info != null && msg.self.info.playerSide != null)
            {
                StaticData.fieldData.ResetData(msg.self.info.playerSide);
            }


            if ( msg.self!=null && msg.self.info!=null && !string.IsNullOrEmpty(msg.self.info.petId))
            {
                roomBase.charactorManager.CreatePet(msg.self.info.petId, msg.self.info.playerId + "");
                petInfos[msg.self.info.playerId] = msg.self.info.petId;
            }

        }

        protected virtual void SCMovePush(object obj)
        {
            SCMovePush msg = (SCMovePush)obj;

            foreach (Position pos in msg.position)
            {
                if (running)
                    queueRoleMove.Enqueue(pos);
                else
                    SolveRoleMove(pos);
            }
            NetAPI.SendSocket(OpDefine.CSMoveConfirm, new CSMoveConfirm());
        }

        protected virtual void SCPlayerAppear(object obj)
        {
            SCPlayerAppear msg = (SCPlayerAppear)obj;
            foreach (MovePlayer player in msg.player)
            {
                if (running)
                    queueRoleAppear.Enqueue(player);
                else
                    SolveRoleAppear(player);
            }
        }

        protected virtual void SCPlayerDisappear(object obj)
        {
            SCPlayerDisappear msg = (SCPlayerDisappear)obj;
            //Debug.Log("role disappear count " + msg.playerId.Count);
            foreach (long id in msg.playerId)
            {
                if (id == StaticData.playerData.playerId)
                {
                    Debug.LogError("Self disappear receive " + id);
                }
                else
                {
                    if (running)
                        queueRoleDisappear.Enqueue(id);
                    else
                        SolveRoleDisappear(id);
                }
            }
        }

        protected virtual void SCMovePlayerInfo(object obj)
        {
            SCMovePlayerInfo msg = (SCMovePlayerInfo)obj;
            foreach (var info in msg.playerInfos)
            {
                if (running)
                    queueRoleInfo.Enqueue(info);
                else
                    SolveRoleInfo(info);
            }
        }

        public virtual void SCPublicMessage(object obj)
        {
            var msg = (SCPublicMessage)obj;
            if(msg.pubmsg.type == 1)
            {
                BoxManager.CreateMarqueeBox(msg.pubmsg.msg);
            }

            Debug.Log("[SCPublicMessage] @@@");
        }

        #endregion
    }
}

